package com.hsurosy.domain.award.service;

import com.hsurosy.domain.award.event.SendAwardMessageEvent;
import com.hsurosy.domain.award.model.aggregate.UserAwardRecordAggregate;
import com.hsurosy.domain.award.model.entity.DistributeAwardEntity;
import com.hsurosy.domain.award.model.entity.TaskEntity;
import com.hsurosy.domain.award.model.entity.UserAwardRecordEntity;
import com.hsurosy.domain.award.model.valobj.TaskStateVO;
import com.hsurosy.domain.award.repository.IAwardRepository;
import com.hsurosy.domain.award.service.distribute.IDistributeAward;
import com.hsurosy.types.event.BaseEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Map;

/**
 * @Author Hsu琛君珩
 * @Date 2024-11-14 11:11
 * @Description 奖品服务
 * @Version: v1.0.0
 */
@Slf4j
@Service
public class AwardService implements IAwardService {

    private final IAwardRepository awardRepository; // 奖品存储库接口
    private final SendAwardMessageEvent sendAwardMessageEvent; // 奖品发送事件处理
    private final Map<String, IDistributeAward> distributeAwardMap; // 奖品分发实现映射

    public AwardService(IAwardRepository awardRepository, SendAwardMessageEvent sendAwardMessageEvent, Map<String, IDistributeAward> distributeAwardMap) {
        this.awardRepository = awardRepository;
        this.sendAwardMessageEvent = sendAwardMessageEvent;
        this.distributeAwardMap = distributeAwardMap;
    }

    /**
     * 保存用户奖品记录
     * 1. 构建发送奖品的消息对象。
     * 2. 构建消息任务对象，用于后续的消息发送管理。
     * 3. 构建聚合对象，将用户奖品记录和任务消息绑定在同一事务中保存。
     *
     * @param userAwardRecordEntity 用户奖品记录实体
     */
    @Override
    public void saveUserAwardRecord(UserAwardRecordEntity userAwardRecordEntity) {
        // 1. 构建消息对象
        SendAwardMessageEvent.SendAwardMessage sendAwardMessage = new SendAwardMessageEvent.SendAwardMessage();
        sendAwardMessage.setUserId(userAwardRecordEntity.getUserId()); // 设置用户ID
        sendAwardMessage.setOrderId(userAwardRecordEntity.getOrderId());
        sendAwardMessage.setAwardId(userAwardRecordEntity.getAwardId()); // 设置奖品ID
        sendAwardMessage.setAwardTitle(userAwardRecordEntity.getAwardTitle()); // 设置奖品标题
        sendAwardMessage.setAwardConfig(userAwardRecordEntity.getAwardConfig());

        // 构建消息事件
        BaseEvent.EventMessage<SendAwardMessageEvent.SendAwardMessage> sendAwardMessageEventMessage = sendAwardMessageEvent.buildEventMessage(sendAwardMessage);

        // 2. 构建任务对象
        TaskEntity taskEntity = new TaskEntity();
        taskEntity.setUserId(userAwardRecordEntity.getUserId()); // 任务关联的用户ID
        taskEntity.setTopic(sendAwardMessageEvent.topic()); // 消息的主题
        taskEntity.setMessageId(sendAwardMessageEventMessage.getId()); // 消息的唯一ID
        taskEntity.setMessage(sendAwardMessageEventMessage); // 消息内容
        taskEntity.setState(TaskStateVO.create); // 初始状态为"创建"

        // 3. 构建聚合对象
        UserAwardRecordAggregate userAwardRecordAggregate = UserAwardRecordAggregate.builder()
                .taskEntity(taskEntity) // 添加任务实体
                .userAwardRecordEntity(userAwardRecordEntity) // 添加用户奖品记录实体
                .build();

        // 4. 存储聚合对象 - 确保用户奖品记录和任务消息在同一事务中完成
        awardRepository.saveUserAwardRecord(userAwardRecordAggregate);

        log.info("中奖记录保存完成 userId: {} orderId: {}", userAwardRecordEntity.getUserId(), userAwardRecordEntity.getOrderId());
    }

    /**
     * 分发奖品
     *
     * @param distributeAwardEntity 分发奖品的实体对象
     */
    @Override
    public void distributeAward(DistributeAwardEntity distributeAwardEntity) {
        // 查询奖品Key
        String awardKey = awardRepository.queryAwardKey(distributeAwardEntity.getAwardId());
        if (null == awardKey) {
            log.error("分发奖品，奖品ID不存在，awardKey: {}", awardKey);
            return;
        }

        // 获取奖品分发服务
        IDistributeAward distributeAward = distributeAwardMap.get(awardKey);
        if (null == distributeAward) {
            log.error("分发奖品，对应的服务不存在，awardKey: {}", awardKey);
            // TODO 后续完善全部奖品分发服务后开启异常抛出
            // throw new RuntimeException("分发奖品，奖品" + awardKey + "对应的服务不存在");
            return;
        }

        // 调用奖品分发服务发放奖品
        distributeAward.giveOutPrizes(distributeAwardEntity);
    }

}
